<template>
  <el-dialog v-model="dialogVisible"
             :title="title"
             width="1080"
             destroy-on-close
             @closed="handleClose">
    <!-- 搜索表单 -->
    <el-form :inline="true"
             :model="searchForm"
             class="search-form">
      <template v-for="field in searchFields"
                :key="field.prop">
        <el-form-item :label="field.label">
          <el-input v-if="field.type === 'input'"
                    v-model="searchForm[field.prop]"
                    :placeholder="'请输入' + field.label"
                    clearable />
          <el-select style="width: 220px"
                     v-if="field.type === 'select'"
                     v-model="searchForm[field.prop]"
                     :placeholder="'请选择' + field.label"
                     clearable>
            <el-option v-for="option in field.options"
                       :key="option.value"
                       :label="option.label"
                       :value="option.value" />
          </el-select>
        </el-form-item>
      </template>
      <el-form-item>
        <el-button type="primary"
                   :icon="Search"
                   @click="handleSearch">
          搜索
        </el-button>
        <el-button :icon="Refresh"
                   @click="handleReset">重置</el-button>
      </el-form-item>
    </el-form>

    <!-- 数据表格 -->
    <el-table v-loading="loading"
              :data="tableData"
              :height="380"
              border
              @selection-change="handleSelectionChange"
              @row-click="handleRowClick"
              highlight-current-row>
      <el-table-column v-if="multiple" type="selection" width="55" />
      <el-table-column v-else width="55">
        <template #default="scope">
          <el-radio v-model="selectedId"
                    :label="scope.row.id"
                    @change="() => handleRadioChange(scope.row)">
            <span></span>
          </el-radio>
        </template>
      </el-table-column>
      <el-table-column type="index"
                       label="序号"
                       width="60" />
      <template v-for="column in tableColumns"
                :key="column.prop">
        <el-table-column :prop="column.prop"
                         :label="column.label"
                         :width="column.width"
                         show-overflow-tooltip />
      </template>
    </el-table>

    <!-- 分页 -->
    <el-pagination v-model:current-page="searchForm.page"
                   v-model:page-size="searchForm.limit"
                   :total="total"
                   :page-sizes="[10, 20, 30, 50]"
                   layout="total, sizes, prev, pager, next"
                   class="pagination"
                   @size-change="handleSizeChange"
                   @current-change="handleCurrentChange" />

    <!-- 底部按钮 -->
    <template #footer>
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary"
                 @click="handleConfirm">确 定</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
import { Search, Refresh } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

// 定义组件属性
const props = defineProps<{
  // 弹框标题
  title: string
  // 弹框显示状态
  modelValue: boolean
  // 搜索字段配置
  searchFields: Array<{
    label: string
    prop: string
    type: 'input' | 'select'
    options?: Array<{ label: string; value: any }>
  }>
  // 表格列配置
  tableColumns: Array<{
    prop: string
    label: string
    width?: number | string
  }>
  // 获取数据的API方法
  fetchDataApi: (params: any) => Promise<any>
  // 是否多选
  multiple?: boolean
}>()

// 定义事件
const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void
  (e: 'confirm', value: any): void
}>()

// 组件状态
const dialogVisible = ref(false)
const loading = ref(false)
const tableData = ref<any[]>([])
const total = ref(0)
const selectedData = ref<any[]>([])
const selectedId = ref<string | number>('')

// 搜索表单
const searchForm = reactive<any>({
  page: 1,
  limit: 10,
})

// 监听弹框显示状态
watch(
  () => props.modelValue,
  (val) => {
    dialogVisible.value = val
    if (val) {
      // 打开弹框时自动执行查询
      fetchData()
    }
  },
  { immediate: true }
)

// 监听内部弹框状态
watch(
  () => dialogVisible.value,
  (val) => {
    emit('update:modelValue', val)
  }
)

// 获取数据
const fetchData = async () => {
  loading.value = true
  try {
    const res = await props.fetchDataApi(searchForm)
    if (res.data) {
      tableData.value = res.data.list
      total.value = res.data.total
    } else {
      tableData.value = []
      total.value = 0
    }
  } catch (error) {
    console.error('获取数据失败:', error)
    tableData.value = []
    total.value = 0
  } finally {
    loading.value = false
  }
}

// 搜索
const handleSearch = () => {
  searchForm.page = 1
  fetchData()
}

// 重置
const handleReset = () => {
  for (const field of props.searchFields) {
    searchForm[field.prop] = undefined
  }
  searchForm.page = 1
  searchForm.limit = 10
  fetchData()
}

// 选择变更（多选模式）
const handleSelectionChange = (selection: any[]) => {
  if (props.multiple) {
    selectedData.value = selection
  }
}

// 单选模式下的行点击处理
const handleRowClick = (row: any) => {
  if (!props.multiple) {
    selectedId.value = row.id
    selectedData.value = [row]
  }
}

// 单选模式下的radio变更处理
const handleRadioChange = (row: any) => {
  selectedData.value = [row]
}

// 分页大小变更
const handleSizeChange = (val: number) => {
  searchForm.limit = val
  fetchData()
}

// 页码变更
const handleCurrentChange = (val: number) => {
  searchForm.page = val
  fetchData()
}

// 确认选择
const handleConfirm = () => {
  if (selectedData.value.length === 0) {
    ElMessage.warning('请至少选择一条记录')
    return
  }
  emit('confirm', props.multiple ? selectedData.value : selectedData.value[0])
  dialogVisible.value = false
}

// 关闭弹框
const handleClose = () => {
  selectedData.value = []
  selectedId.value = ''
  for (const field of props.searchFields) {
    searchForm[field.prop] = undefined
  }
  searchForm.page = 1
  searchForm.limit = 10
}
</script>

<style lang="scss" scoped>
.search-form {
  margin-bottom: 20px;
}

.pagination {
  margin-top: 20px;
  justify-content: flex-end;
}

:deep(.el-radio) {
  margin-right: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

:deep(.el-radio__label) {
  display: none;
}
</style>
